#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>          /* See NOTES */
#include<sys/socket.h>
#include<unistd.h>
#include<pthread.h>
#include<arpa/inet.h>
#include<string.h>

#define N 128

#define ERRLOG(errmsg) do{\
                                                                perror(errmsg);\
                                                                printf("file : %s, func: %s, line : %d", __FILE__, __func__, __LINE__);\
                                                                exit(-1);\
                                                         }while(0);


int num=0;

void *pthread_func(void *arg){
    pthread_detach(pthread_self());
    int acceptfd = *(int *)arg;
    char buf[N] = {0};
    ssize_t bytes;

     while(1){
        if((bytes = recv(acceptfd, buf, N, 0)) == -1){
            num--;
            printf("\e[31;2mnumber=%d\e[0m\n",num);
            printf("Client : [%d] Quit\n",acceptfd);
            pthread_exit(NULL);
        }else if(bytes == 0){
            num--;
            printf("\e[31;2mnumber=%d\e[0m\n",num);
            printf("Client : [%d] Quit\n",acceptfd);
            pthread_exit(NULL);
        }

        printf("number=%d\n", num);
    }      
}

int main(int argc, char const *argv[]){
    if(argc != 3){
        fprintf(stderr, "Usage %s <ip> <port>\n", argv[0]);
        exit(-1);
    }
    int sockfd = -1;
    int acceptfd = -1;
    pthread_t thread;
    struct sockaddr_in servaddr, clientaddr;
    socklen_t addrlen = sizeof(servaddr);
    //第一步：创建套接字
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
        ERRLOG("socket error");
    }

    //第二步：填充ip4网络信息结构体
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    servaddr.sin_port = htons(atoi(argv[2]));

    //第三步：绑定套接字和服务器网络信息结构体
    if(bind(sockfd, (struct sockaddr *)&servaddr, addrlen) == -1){
        ERRLOG("bind error");
    }

    //第四步：设置被动监听状态
    if(listen(sockfd, 5)  == -1){
        ERRLOG("listen error");
    }

    //第五步：阻塞等待客户端连接
while(1){
    if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) == -1){
        ERRLOG("accepet error");
    }



    if(pthread_create(&thread, NULL, pthread_func, &acceptfd) != 0){
        perror("pthread_create error");
        exit(-1);
    }

    num++;

    //打印客户端的网络信息
    printf("Client : [%s : %d],\e[32;2mnumber:%d\e[0m\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port),num);
}
    return 0;
}
